package com.sgcc.nfc.lock.presentation.map

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sgcc.nfc.lock.core.network.NetworkResult
import com.sgcc.nfc.lock.domain.model.MapFilter
import com.sgcc.nfc.lock.domain.model.MapPoint
import com.sgcc.nfc.lock.domain.model.MapStats
import com.sgcc.nfc.lock.domain.model.Region
import com.sgcc.nfc.lock.domain.model.RoomStatus
import com.sgcc.nfc.lock.domain.usecase.GetMapRoomsUseCase
import com.sgcc.nfc.lock.domain.usecase.GetRegionTreeUseCase
import com.sgcc.nfc.lock.domain.model.isClosed
import com.sgcc.nfc.lock.domain.model.isIdle
import com.sgcc.nfc.lock.domain.model.isProblematic
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.launch

@HiltViewModel
class MapViewModel @Inject constructor(
    private val getMapRoomsUseCase: GetMapRoomsUseCase,
    private val getRegionTreeUseCase: GetRegionTreeUseCase
) : ViewModel() {

    private val _uiState = MutableLiveData(MapUiState())
    val uiState: LiveData<MapUiState> = _uiState

    init {
        loadRegions()
        loadPoints()
    }

    fun loadPoints(filter: MapFilter = _uiState.value?.filter ?: MapFilter()) {
        _uiState.update { it.copy(isLoading = true, error = null) }
        viewModelScope.launch {
            when (val result = getMapRoomsUseCase(filter.regionId, filter.status?.let(::statusToCode))) {
                is NetworkResult.Success -> {
                    val points = result.data
                    val stats = computeStats(points)
                    _uiState.update {
                        it.copy(
                            isLoading = false,
                            points = points,
                            stats = stats,
                            filter = filter,
                            error = null
                        )
                    }
                }
                is NetworkResult.Error -> {
                    _uiState.update {
                        it.copy(
                            isLoading = false,
                            error = result.message,
                            points = emptyList(),
                            stats = MapStats(0, 0, 0, 0)
                        )
                    }
                }
                NetworkResult.Loading -> {
                    // no-op handled via isLoading state
                }
            }
        }
    }

    fun applyFilter(filter: MapFilter) {
        loadPoints(filter)
    }

    private fun loadRegions() {
        viewModelScope.launch {
            when (val result = getRegionTreeUseCase()) {
                is NetworkResult.Success -> {
                    _uiState.update { it.copy(regions = result.data) }
                }
                is NetworkResult.Error -> {
                    _uiState.update { it.copy(error = result.message) }
                }
                NetworkResult.Loading -> Unit
            }
        }
    }

    private fun computeStats(points: List<MapPoint>): MapStats {
        val total = points.size
        val closed = points.count { it.isClosed() }
        val open = points.count { it.isProblematic() }
        val idle = points.count { it.isIdle() }
        return MapStats(total, closed, open, idle)
    }

    private fun statusToCode(status: RoomStatus): Int? = when (status) {
        RoomStatus.NORMAL -> 0
        RoomStatus.IN_USE -> 1
        RoomStatus.ALERT -> 2
        RoomStatus.UNKNOWN -> null
    }

    private inline fun MutableLiveData<MapUiState>.update(transform: (MapUiState) -> MapUiState) {
        val current = value ?: MapUiState()
        value = transform(current)
    }
}
